package service

import (
	"gitee.com/ling1314/origin-utility/db"
	"gitee.com/ling1314/origin-utility/model"
	"gitee.com/ling1314/origin-utility/modules/repository"
	"gitee.com/ling1314/origin-utility/utils"
	log "github.com/sirupsen/logrus"
	"gorm.io/gorm"
)

type appService struct {
	baseService
}

func (ser appService) DeleteIssueApp(appId int64) (err error) {

	var (
		ss []model.HostSession
	)
	// 注销关联会话
	if ss, err = repository.HostSessionRepository.FindActionSessionByAppId(appId); err != nil {
		return err
	}
	for i := range ss {
		if err = SessionService.Logoff(ss[i].HostSessionId); err != nil {
			log.Error(err)
		}
	}
	// 删除应用映射
	if err = repository.AppRepository.DeleteMapDeptAppForAppId(appId); err != nil {
		return err
	}
	if err = repository.AppRepository.DeleteMapDirectAppForAppId(appId); err != nil {
		return err
	}
	// 删除应用
	if err = repository.AppRepository.DeleteIssueApp(appId); err != nil {
		return err
	}
	return nil
}

func (ser appService) GetIssueList(str string) (li []model.AppDetail, err error) {
	var (
		as []model.AppIssue
	)
	if as, err = repository.AppRepository.FindIssueList(str); err != nil {
		return
	}
	li = make([]model.AppDetail, len(as))
	for i := range as {
		var clu model.Cluster
		if clu, err = repository.ClusterRepository.FindById(as[i].ClusterId); err != nil {
			return
		}
		li[i] = model.AppDetail{
			AppIssue: as[i],
			Cluster:  clu,
		}
	}
	return
}

func (ser appService) GetAppIssueInfo(id int64) (m model.AppIssue, err error) {
	if m, err = repository.AppRepository.FindAppIssueById(id); err != nil {
		return
	}
	return m, nil
}

func (ser appService) GetAppInstallList(clusterId int64) (li []model.AppInstall, err error) {
	return repository.AppRepository.FindAppInstallListByClusterId(clusterId)
}

func (ser appService) CheckIssueStatus(ids []int64, clusterId int64) (li []model.AppInstall, err error) {
	if li, err = repository.AppRepository.FindAppInstallListByIds(ids); err != nil {
		return nil, err
	}
	for i := range li {
		var b bool
		if _, b, err = repository.AppRepository.CheckIssueStatus(li[i].ExePath, li[i].WorkSpace, li[i].AppParams, clusterId); err != nil {
			return nil, err
		}
		li[i].IsInstalled = b
	}
	return li, nil
}

func (ser appService) IssueApp(form model.IssueAppForm) error {
	return db.GetDB().Transaction(func(tx *gorm.DB) error {
		for i := range form.AppInstallIds {
			var (
				err       error
				appSource model.AppInstall
				dai       model.AppIssue
				ai        model.AppIssue
				ah        model.AppHost
				b         bool
			)
			if appSource, err = repository.AppRepository.FindAppInstallById(form.AppInstallIds[i]); err != nil {
				return err
			}
			if ah, err = repository.HostRepository.FindById(appSource.HostId); err != nil {
				return err
			}

			if dai, b, err = repository.AppRepository.CheckIssueStatusForAll(appSource.ExePath, appSource.WorkSpace, appSource.AppParams,
				form.DisplayMode, form.IsAdmin, ah.ClusterID); err != nil {
				return err
			}
			if form.Alias == "" {
				form.Alias = appSource.AppName
			}
			if !b {
				ai = model.AppIssue{
					AppId:       utils.GetSoftId(),
					AppName:     appSource.AppName,
					Alias:       form.Alias,
					Icon:        appSource.Icon,
					LinkPath:    appSource.LinkPath,
					ExecPath:    appSource.ExePath,
					AppParams:   appSource.AppParams,
					WorkSpace:   appSource.WorkSpace,
					DisplayMode: form.DisplayMode,
					IsAdmin:     form.IsAdmin,
					IsSingle:    form.IsSingle,
					ClusterId:   ah.ClusterID,
					IsPublic:    form.IsPublic,
				}
				if err = repository.AppRepository.InsertAppIssue(&ai); err != nil {
					return err
				}
			} else {
				ai = model.AppIssue{
					AppId:       dai.AppId,
					AppName:     appSource.AppName,
					Alias:       form.Alias,
					Icon:        appSource.Icon,
					LinkPath:    appSource.LinkPath,
					ExecPath:    appSource.ExePath,
					AppParams:   appSource.AppParams,
					WorkSpace:   appSource.WorkSpace,
					DisplayMode: form.DisplayMode,
					IsAdmin:     form.IsAdmin,
					IsSingle:    form.IsSingle,
					ClusterId:   ah.ClusterID,
					IsPublic:    form.IsPublic,
				}
				if err = repository.AppRepository.UpdateAppIssue(&ai); err != nil {
					return err
				}
			}
			// 写入发布映射
			if !form.IsPublic {
				if err = repository.AppRepository.DeleteMapDirectAppForAppId(ai.AppId); err != nil {
					return err
				}
				if err = repository.AppRepository.DeleteMapDeptAppForAppId(ai.AppId); err != nil {
					return err
				}
				if err = repository.AppRepository.InsertMapDeptApp(ai.AppId, form.IssueDeptIds); err != nil {
					return err
				}
				if err = repository.AppRepository.InsertMapDirectApp(ai.AppId, form.IssueUserIds); err != nil {
					return err
				}
			}
		}
		return nil
	})
}

func (ser appService) GetSelfAppList(self *utils.CustomClaims) (li []*model.AppDetail, err error) {
	var (
		ids     []int64
		gli     []model.AppIssue
		dli     []int64
		uli     []int64
		u       *model.User
		appList []model.AppIssue
	)
	if u, err = repository.UserRepository.FindById(self.UserID); err != nil {
		return nil, err
	}
	if gli, err = repository.AppRepository.FindGlobalApps(); err != nil {
		return nil, err
	}
	if dli, err = repository.AppRepository.FindDeptAppIds(u.DeptId); err != nil {
		return nil, err
	}
	if uli, err = repository.AppRepository.FindUserAppIds(u.UserId); err != nil {
		return nil, err
	}
	ids = make([]int64, len(gli))
	for i := range gli {
		ids[i] = gli[i].AppId
	}
	for i := range dli {
		if !utils.Contains(ids, dli[i]) {
			ids = append(ids, dli[i])
		}
	}
	for i := range uli {
		if !utils.Contains(ids, uli[i]) {
			ids = append(ids, uli[i])
		}
	}
	if appList, err = repository.AppRepository.FindIssueApps(ids); err != nil {
		return nil, err
	}
	li = make([]*model.AppDetail, len(appList))
	for i := range appList {
		var clu model.Cluster
		if clu, err = repository.ClusterRepository.FindById(appList[i].ClusterId); err != nil {
			return nil, err
		}
		item := &model.AppDetail{
			AppIssue: appList[i],
			Cluster:  clu,
		}
		li[i] = item
	}
	return li, nil
}
